上一篇提到了函式的控制結構以及錯誤處理的方式,對函式已經有了基本的了解,這一篇將會探討如何實作合約的繼承
在實作合約的繼承前,需要先了解函式的作用域。在 Solidity 中,函式有四種作用域,分別是 public
、 private
、 internal
與 external
。
這是最常見的作用域,也是預設的作用域,所有成員都可以呼叫。
這也是常見的作用域,可以給當前合約內部使用,無法直接由外部呼叫,也無法給繼承的合約使用。
這與多數物件導向語言的 protected
相似,可以在合約內部使用,包含了繼承的合約,但無法由外部呼叫。
這是比較特別的作用域,只能夠給外部使用,適合用來處理資料,並要在參數帶上 calldata
。由於只開放給外部使用,比起同時要開放給內部使用的 public
還要省 Gas。
基本上,我認為 external
是 public static
的變形,就是用來呼叫的運算邏輯。
function test(uint[] calldata array) external pure returns (uint[] memory) {
return array;
}
與多數的物件導向語言繼承概念差不多,不過不是使用 extends
而是 is
。也許會有人提問:這樣在部署的時候會產生幾個合約?(沒錯,又是剛開始學 Solidity 時的我)這個問題的答案就是 一個 ,因為 Solidity 會將繼承的合約程式碼複製到自身,所以不必擔心產生多個合約造成管理上的困難,那這邊我們就寫兩個合約來實作,分別是 商店 與 員工 。
商店合約裡面設定 struct
來定義我們商品的庫存類別,並在創建時個設定為100,並提供 raise
函式增加商品存貨,以及 reduce
函式減少商品庫存。
pragma solidity ^0.5.0;
contract Store {
struct goodsCount {
uint candy;
uint cookie;
uint bread;
}
goodsCount internal stock;
constructor() public {
stock = goodsCount({
candy: 100,
cookie: 100,
bread: 100
});
}
function reduce(string memory name, uint quantity) internal {
bytes32 inputName = keccak256(bytes(name));
bytes32[3] memory goodsList = [keccak256(bytes("candy")), keccak256(bytes("cookies")), keccak256(bytes("bread"))];
if (inputName == goodsList[0] && stock.candy >= quantity) {
stock.candy -= quantity;
} else if(inputName == goodsList[1] && stock.cookie >= quantity) {
stock.cookie -= quantity;
} else if(inputName == goodsList[2] && stock.bread >= quantity) {
stock.bread -= quantity;
} else {
revert("Stock is undefined or is not enough.");
}
}
function raise(string memory name, uint quantity) internal {
bytes32 inputName = keccak256(bytes(name));
bytes32[3] memory goodsList = [keccak256(bytes("candy")), keccak256(bytes("cookies")), keccak256(bytes("bread"))];
if (inputName == goodsList[0]) {
stock.candy += quantity;
} else if(inputName == goodsList[1]) {
stock.cookie += quantity;
} else if(inputName == goodsList[2]) {
stock.bread += quantity;
}
}
}
由於 Solidity 無法直接進行字串比對,所以運用
keccak256(bytes32 memory)
來進行
先使用 import
將商店合約引入,並用 is
來繼承。員工合約提供 sell
函式來販售商品,以 purchase
函式來進貨商品,以及使用 showStocks
來顯示存貨狀況。
pragma solidity ^0.5.0;
import "./Store.sol";
contract Staff is Store {
function sell(string memory name, uint quantity) public {
reduce(name, quantity);
}
function purchase(string memory name, uint quantity) public {
raise(name, quantity);
}
function showStocks() external view returns (uint, uint, uint) {
return (stock.candy, stock.cookie, stock.bread);
}
}
了解函式的作用域,並學習合約的繼承,將作用域運用在合約實作當中!另外字串比對的部分可以參考下方的資料,有許多種字串比對的方式,各有優缺點,各位開發者自行斟酌呦!